package com.ruoyi.common.core.utils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * @Description: 图片合并
 * @Author: j.zh
 * @Date: 2023/3/9
 * @Version: 1.0
 **/
public class ImageMergeUtils {
    /**
     * @param fileUrl 文件绝对路径或相对路径
     * @return 读取到的缓存图像
     * @throws IOException 路径错误或者不存在该文件时抛出IO异常
     */
    public static BufferedImage getBufferedImage(String fileUrl) throws IOException {
        File f = new File(fileUrl);
        return ImageIO.read(f);
    }

    /**
     * 远程图片转BufferedImage
     *
     * @param destUrl 远程图片地址
     * @return
     */
    public static BufferedImage getBufferedImageDestUrl(String destUrl) {
        HttpURLConnection conn = null;
        BufferedImage image = null;
        try {
            URL url = new URL(destUrl);
            conn = (HttpURLConnection) url.openConnection();
            int responseCode = conn.getResponseCode();
            if (responseCode == 200) {
                image = ImageIO.read(conn.getInputStream());
                return image;
            } else {
                System.out.println("HTTP Response Code: " + responseCode);
                System.out.println("HTTP Response Message: " + conn.getResponseMessage());
                // 适当的错误处理
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            conn.disconnect();
        }
        return image;
    }

    /**
     * @Description: 获取网络图片的长和宽
     * @Author: j.zh
     * @Date: 2024/6/17
     * @param destUrl
     * @return
     * @Version: 4.0.0
    **/
    public static List<Integer> getImageWidthAndHeight(String destUrl){
        BufferedImage image = getBufferedImageDestUrl(destUrl);
        List<Integer> size = new ArrayList<>();
        size.add(image.getHeight());
        size.add(image.getWidth());
        return size;
    }

    /**
     * 输出图片
     *
     * @param buffImg  图像拼接叠加之后的BufferedImage对象
     * @param savePath 图像拼接叠加之后的保存路径
     */
    public static void generateSaveFile(BufferedImage buffImg, String savePath) {
        int temp = savePath.lastIndexOf(".") + 1;
        try {
            File outFile = new File(savePath);
            if (!outFile.exists()) {
                outFile.createNewFile();
            }
            ImageIO.write(buffImg, savePath.substring(temp), outFile);
            System.out.println("ImageIO write...");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * @param buffImg  源文件(BufferedImage)
     * @param waterImg 水印文件(BufferedImage)
     * @param x        距离右下角的X偏移量
     * @param y        距离右下角的Y偏移量
     * @param alpha    透明度, 选择值从0.0~1.0: 完全透明~完全不透明
     * @return BufferedImage
     * @throws IOException
     * @Title: 构造图片
     * @Description: 生成水印并返回java.awt.image.BufferedImage
     */
    public static BufferedImage overlyingImage(BufferedImage buffImg, BufferedImage waterImg, int x, int y, float alpha)
            throws IOException {

        // 创建Graphics2D对象，用在底图对象上绘图
        Graphics2D g2d = buffImg.createGraphics();
        int waterImgWidth = waterImg.getWidth();// 获取层图的宽度
        int waterImgHeight = waterImg.getHeight();// 获取层图的高度
        // 在图形和图像中实现混合和透明效果
        g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
        // 绘制
        g2d.drawImage(waterImg, x, y, waterImgWidth, waterImgHeight, null);
        g2d.dispose();// 释放图形上下文使用的系统资源
        return buffImg;
    }

    /**
     * 待合并的两张图必须满足这样的前提，如果水平方向合并，则高度必须相等；如果是垂直方向合并，宽度必须相等。 mergeImage方法不做判断，自己判断。
     *
     * @param img1         待合并的第一张图
     * @param img2         带合并的第二张图
     * @param isHorizontal 为true时表示水平方向合并，为false时表示垂直方向合并
     * @return 返回合并后的BufferedImage对象
     * @throws IOException
     */
    public static BufferedImage mergeImage(BufferedImage img1, BufferedImage img2, boolean isHorizontal)
            throws IOException {
        int w1 = img1.getWidth();
        int h1 = img1.getHeight();
        int w2 = img2.getWidth();
        int h2 = img2.getHeight();

        // 从图片中读取RGB
        int[] ImageArrayOne = new int[w1 * h1];
        ImageArrayOne = img1.getRGB(0, 0, w1, h1, ImageArrayOne, 0, w1); // 逐行扫描图像中各个像素的RGB到数组中
        int[] ImageArrayTwo = new int[w2 * h2];
        ImageArrayTwo = img2.getRGB(0, 0, w2, h2, ImageArrayTwo, 0, w2);

        // 生成新图片
        BufferedImage DestImage = null;
        if (isHorizontal) { // 水平方向合并
            DestImage = new BufferedImage(w1 + w2, h1, BufferedImage.TYPE_INT_RGB);
            DestImage.setRGB(0, 0, w1, h1, ImageArrayOne, 0, w1); // 设置上半部分或左半部分的RGB
            DestImage.setRGB(w1, 0, w2, h2, ImageArrayTwo, 0, w2);
        } else { // 垂直方向合并
            DestImage = new BufferedImage(w1, h1 + h2, BufferedImage.TYPE_INT_RGB);
            DestImage.setRGB(0, 0, w1, h1, ImageArrayOne, 0, w1); // 设置上半部分或左半部分的RGB
            DestImage.setRGB(0, h1, w2, h2, ImageArrayTwo, 0, w2); // 设置下半部分的RGB
        }

        return DestImage;
    }

    public static void imageAddWatermark(String srcFileUrl) {

        File srcFolder = new File(srcFileUrl);
        // int i = 0;
        for (File file : srcFolder.listFiles()) {
            // File srcImgFile = new File(srcFileUrl);//得到文件

            if (file.isFile() && (file.getName().endsWith(".jpg") || file.getName().endsWith(".png"))) {
                Image srcImg = null;
                try {
                    srcImg = ImageIO.read(file);
                } catch (IOException e1) {
                    e1.printStackTrace();
                } // 文件转化为图片
                int srcImgWidth = srcImg.getWidth(null);// 获取图片的宽
                int srcImgHeight = srcImg.getHeight(null);// 获取图片的高

                // 加水印
                Font font = new Font("微软雅黑", Font.PLAIN, 10);
                BufferedImage bufImg = new BufferedImage(srcImgWidth, srcImgHeight, BufferedImage.TYPE_INT_RGB);
                Graphics2D graphics2d = bufImg.createGraphics();
                graphics2d.drawImage(srcImg, 0, 0, srcImgWidth, srcImgHeight, null);
                graphics2d.setColor(Color.WHITE); // 设置水印颜色
                graphics2d.setFont(font); // 设置字体
                // 设置水印的坐标
                String name = file.getName();
                String waterMarkContent = name.substring(0, name.indexOf("."));
                // System.out.println(getWatermarkLength(waterMarkContent, graphics2d));
                int x = srcImgWidth - getWatermarkLength(waterMarkContent, graphics2d) - 3;
                int y = srcImgHeight - 3;
                graphics2d.drawString(waterMarkContent, x, y); // 画出水印
                graphics2d.dispose();
                // 输出图片
                FileOutputStream outImgStream = null;
                try {
                    outImgStream = new FileOutputStream(file);
                } catch (FileNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                try {
                    ImageIO.write(bufImg, "jpg", outImgStream);
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                try {
                    outImgStream.flush();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                try {
                    outImgStream.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

        }

    }

    public static int getWatermarkLength(String waterMarkContent, Graphics2D g) {
        return g.getFontMetrics(g.getFont()).charsWidth(waterMarkContent.toCharArray(), 0, waterMarkContent.length());
    }

    /**
     * Java 测试图片叠加方法
     */
    public static void overlyingImageTest(String sourceFilePath, String waterFilePath, String saveFilePath) {
//
//        String sourceFilePath = "E://project//imgTest//img//3333.png";
//        String waterFilePath = "E://project//imgTest//img//66.png";
//        String saveFilePath = "E://project//imgTest//img//New6.png";
        try {
            boolean http = sourceFilePath.startsWith("http");
            boolean https = sourceFilePath.startsWith("https");
            BufferedImage bufferImage1 = sourceFilePath.startsWith("http") ? getBufferedImageDestUrl(sourceFilePath)
                    : getBufferedImage(sourceFilePath);
            BufferedImage bufferImage2 = waterFilePath.startsWith("http") ? getBufferedImageDestUrl(waterFilePath)
                    : getBufferedImage(waterFilePath);

            // 构建叠加层
            BufferedImage buffImg = overlyingImage(bufferImage1, bufferImage2, 0, 0, 1.0f);
            // 输出水印图片
            generateSaveFile(buffImg, saveFilePath);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * Java 测试图片合并方法
     */
    public static String imageMargeTest() {
        // 读取待合并的文件
        BufferedImage bi1 = null;
        BufferedImage bi2 = null;
        // 调用mergeImage方法获得合并后的图像
        BufferedImage destImg = null;
        System.out.println("下面是垂直合并的情况：");
        String saveFilePath = "D://test//new1.jpg";
        String divingPath = "D://test//new2.jpg";
        String margeImagePath = "D://test//margeNew.jpg";
        try {
            bi1 = getBufferedImage(saveFilePath);
            bi2 = getBufferedImage(divingPath);
            // 调用mergeImage方法获得合并后的图像
            destImg = mergeImage(bi1, bi2, false);
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 保存图像
        generateSaveFile(destImg, margeImagePath);
        System.out.println("垂直合并完毕!");
        return "垂直合并完毕!";
    }

    /**
     * Java 测试图片合并方法
     *
     * @param i
     */
    public static String overlyingImageTest(int i) {
        // 读取待合并的文件
        BufferedImage bi1 = null;
        BufferedImage bi2 = null;
        // 调用mergeImage方法获得合并后的图像
        BufferedImage destImg = null;
        System.out.println("下面是水平合并的情况：");
        String saveFilePath = "D://test//new1.jpg";
        String divingPath = "D://test//new2.jpg";
        String margeImagePath = "D://test//margeNew" + i + ".jpg";
        try {
            bi1 = getBufferedImage(saveFilePath);
            bi2 = getBufferedImage(divingPath);
            // 调用mergeImage方法获得合并后的图像
            destImg = overlyingImage(bi1, bi2, 0, 0, 1.0f);
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 保存图像
        generateSaveFile(destImg, margeImagePath);
        System.out.println("水平合并完毕!");
        return "水平合并完毕!";
    }


	public static void main(String[] args) throws Exception {
//		long start = System.currentTimeMillis();
        ExecutorService executorService = Executors.newFixedThreadPool(10);

        ArrayList<Future<String>> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            int x = i;
            Callable<String> callable1 = () -> ImageMergeUtils.overlyingImageTest(x);
//			FutureTask<String> task1 = new FutureTask<>(callable1);
            Future<String> submit = executorService.submit(callable1);
            list.add(submit);
        }

        for (Future<String> future : list) {
            future.get();
        }

//		Callable<String> callable1 = ImageMergeUtils::imageMargeTest;
//		FutureTask<String> task1 = new FutureTask<>(callable1);
//
//		ExecutorService executorService = Executors.newFixedThreadPool(10);
//
//		ArrayList<Future<String>> list = new ArrayList<>();
//		for (int i = 0; i < 10; i++) {
//			int x = i;
//			Callable<String> callable1 = () -> ImageMergeUtils.overlyingImageTest(x);
////			FutureTask<String> task1 = new FutureTask<>(callable1);
//			Future<String> submit = executorService.submit(callable1);
//			list.add(submit);
//		}
//
//		for (Future<String> future : list) {
//			future.get();
//		}
//
////		Callable<String> callable1 = ImageMergeUtils::imageMargeTest;
////		FutureTask<String> task1 = new FutureTask<>(callable1);
////
////		executorService.submit(task);
////		executorService.submit(task1);
////
////		String string = task.get();
////		String string1 = task1.get();
//
////		System.out.println(string);
////		System.out.println(string1);
//
////		for (int i = 0; i < 10; i++) {
////			// 测试图片的叠加
////			overlyingImageTest(i);
////		}
////		// 测试图片的垂直合并
////		imageMargeTest();
//		long end = System.currentTimeMillis();
//		System.out.println(end - start);
////        String a = "common-product/2023/05/04/93B2F348E0DC4BE89B262B42EBF4E77D.png;";
////        System.out.println(a.split(";")[0]);

		overlyingImageTest(1);
    }
}
